package cn.cloudtogo.server.mysql;

import cn.cloudtogo.common.GendbException;
import cn.cloudtogo.common.model.DatasourceTypes;
import cn.cloudtogo.common.model.ExternalDatasourceDao;
import cn.cloudtogo.common.model.ExternalDatasourceModel;
import cn.cloudtogo.common.types.ConnectString;
import cn.cloudtogo.common.types.Credential;
import cn.cloudtogo.common.types.Endpoint;
import cn.cloudtogo.common.types.RequestHeaderObject;
import cn.cloudtogo.common.util.JdbcConnectionHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static cn.cloudtogo.common.types.RequestHeaderObject.extractExternalDatasourceModel;

/**
 * @author yaolianhua789@gmail.com
 **/
@Component
@Slf4j
public class SpringJdbcTemplateContext {

    public final Map<String, JdbcTemplate> jdbcTemplateContainer = new ConcurrentHashMap<>(32);

    public synchronized void putJdbcTemplate(RequestHeaderObject object, JdbcTemplate jdbcTemplate) {
        jdbcTemplateContainer.put(object.getUuid(), jdbcTemplate);
    }

    private final ExternalDatasourceDao externalDatasourceDao;

    public synchronized void remove(RequestHeaderObject requestHeaderObject) {
        jdbcTemplateContainer.remove(requestHeaderObject.getUuid());
    }

    public SpringJdbcTemplateContext(ExternalDatasourceDao externalDatasourceDao) {
        this.externalDatasourceDao = externalDatasourceDao;
    }

    public synchronized JdbcTemplate getJdbcTemplate(RequestHeaderObject o) {
        ExternalDatasourceModel model = extractExternalDatasourceModel(o);
        if (!isValid(model)) {
            throw new GendbException("key has been removed");
        }
        JdbcTemplate jdbcTemplate = jdbcTemplateContainer.get(o.getUuid());
        //
        if (jdbcTemplate == null) {
            ConnectString connectString = new ConnectString(
                    DatasourceTypes.Mysql,
                    Credential.of(model.getUsername(), model.getPassword()),
                    Endpoint.of(model.getHost(), model.getPort()),
                    model.getSchema()
            );
            boolean validConnection = JdbcConnectionHelper.isValidConnection(connectString);
            if (validConnection) {
                log.info("get jdbcTemplate null from memory, create new one and return [{}]", model);
                JdbcTemplate templateNew = JdbcConnectionHelper.getJdbcTemplate(connectString);
                this.putJdbcTemplate(o, templateNew);
                return templateNew;
            }
            throw new GendbException(String.format("key is invalid [%s]", o.getUuid()));
        }

        return jdbcTemplate;
    }

    private boolean isValid(ExternalDatasourceModel model) {
        ExternalDatasourceModel one = externalDatasourceDao.query(model.getUuid());
        return one != null;
    }

}
